package com.siyu.tickets.web;

import static com.siyu.common.web.Constants.PROCESS_URL;
import static com.siyu.common.web.Constants.RETURN_URL;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.util.UrlPathHelper;

import com.siyu.common.web.SessionProvider;
import com.siyu.core.manager.AuthenticationMng;
import com.siyu.core.manager.SysUserMng;
import com.siyu.tickets.entity.SysUser;

/**
 * 上下文信息拦截器
 * 
 * 包括登陆信息，权限信息等
 * 
 */
public class AdminContextInterceptor extends HandlerInterceptorAdapter {
	private static final Logger log = LoggerFactory.getLogger(AdminContextInterceptor.class);

	public static final String AUTH_KEY = "auth_key";
	public static final String USERNAME = "user_name";

	public static final String SITE_PARAM = "_site_id_param";
	public static final String SITE_COOKIE = "_site_id_cookie";
	public static final String PERMISSION_MODEL = "_permission_key";

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		// 获得用户
		SysUser user = null;
		if (adminId != null) {
			// 指定管理员（开发状态）
			user = sysUserMng.findById(adminId);
			if (user == null) {
				throw new IllegalStateException("User ID=" + adminId + " not found!");
			}
		} else {
			// 正常状态
			Integer userId = authMng.retrieveUserIdFromSession(session, request, response);
			user = ThreadVariable.getUser();
			if (user == null && userId != null) {
				user = sysUserMng.findById(userId);
			}
		}
		// 此时用户可以为null
		SysUtils.setUser(request, user);
		// User加入线程变量
		ThreadVariable.setUser(user);

		String uri = getURI(request);
		// 不在验证的范围内
		if (exclude(uri)) {
			return true;
		}
		// 用户为null跳转到登陆页面
		if (user == null) {
			response.sendRedirect(getLoginUrl(request));
			return false;
		}
		return true;
	}

	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// Sevlet容器有可能使用线程池，所以必须手动清空线程变量。
		ThreadVariable.removeUser();
	}

	private String getLoginUrl(HttpServletRequest request) {
		StringBuilder buff = new StringBuilder();
		if (loginUrl.startsWith("/")) {
			String ctx = request.getContextPath();
			if (!StringUtils.isBlank(ctx)) {
				buff.append(ctx);
			}
		}
		buff.append(loginUrl);
		StringBuffer param = new StringBuffer();
		if (!StringUtils.isBlank(returnUrl)) {
			param.append(RETURN_URL).append("=").append(returnUrl);
		}

		if (!StringUtils.isBlank(processUrl)) {
			param.append(param.length() > 0 ? "&" : "");
			param.append(PROCESS_URL).append("=").append(getProcessUrl(request));
		}
		buff.append(param.length() > 0 ? "?" : "").append(param);
		return buff.toString();
	}

	private String getProcessUrl(HttpServletRequest request) {
		StringBuilder buff = new StringBuilder();
		if (loginUrl.startsWith("/")) {
			String ctx = request.getContextPath();
			if (!StringUtils.isBlank(ctx)) {
				buff.append(ctx);
			}
		}
		buff.append(processUrl);
		return buff.toString();
	}

	private boolean exclude(String uri) {
		if (excludeUrls != null) {
			for (String exc : excludeUrls) {
				if (exc.equals(uri)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * 获得第三个路径分隔符的位置
	 * 
	 * @param request
	 * @throws IllegalStateException
	 *             访问路径错误，没有三(四)个'/'
	 */
	private static String getURI(HttpServletRequest request) throws IllegalStateException {
		UrlPathHelper helper = new UrlPathHelper();
		String uri = helper.getOriginatingRequestUri(request);
		String ctxPath = helper.getOriginatingContextPath(request);
		int start = 0;
		if (!StringUtils.isBlank(ctxPath)) {
			start = uri.indexOf('/', 1);
		}
		if (start < 0) {
			return "/";
		}
		return uri.substring(start);
	}

	@Autowired
	private SessionProvider session;
	@Autowired
	private AuthenticationMng authMng;
	@Autowired
	private SysUserMng sysUserMng;

	private Integer adminId;
	private String[] excludeUrls;
	private String loginUrl;
	private String processUrl;
	private String returnUrl;

	public void setAdminId(Integer adminId) {
		this.adminId = adminId;
	}

	public void setExcludeUrls(String[] excludeUrls) {
		this.excludeUrls = excludeUrls;
	}

	public void setLoginUrl(String loginUrl) {
		this.loginUrl = loginUrl;
	}

	public void setProcessUrl(String processUrl) {
		this.processUrl = processUrl;
	}

	public void setReturnUrl(String returnUrl) {
		this.returnUrl = returnUrl;
	}

}
